package com.jymj.service.impl;

import com.jymj.dao.GanttLinkDao;
import com.jymj.dao.PjTaskDao;
import com.jymj.dao.PjTaskDelDao;
import com.jymj.entity.KeyValueEntity;
import com.jymj.entity.gantt.GanttLinkEntity;
import com.jymj.entity.gantt.PjTaskDetEntity;
import com.jymj.entity.gantt.PjTaskEntity;
import com.jymj.enumEntity.ChildProEnum;
import com.jymj.service.PjTaskService;
import com.jymj.utils.ParseUtils;
import org.apache.commons.lang.text.StrBuilder;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by dl on 2017/7/26.
 */
@Service("pjTaskService")
public class PjTaskServiceImpl implements PjTaskService {

    private final Logger LOGGER = LoggerFactory.getLogger(PjTaskServiceImpl.class);
    @Autowired
    private PjTaskDao pjTaskDao;
    @Autowired
    private PjTaskDelDao pjTaskDelDao;
    @Autowired
    private GanttLinkDao ganttLinkDao;

    @Override
    public PjTaskEntity queryObject(Integer taskId) {
        return pjTaskDao.queryObject(taskId);
    }

    @Override
    public PjTaskEntity queryObject1(String code, Integer taskid) {
        PjTaskEntity t = new PjTaskEntity();
        t.setCode(code);
        t.setTaskid(taskid);
        return pjTaskDao.queryObject1(t);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return 0;
    }

    @Override
    public void save(PjTaskEntity task) {
        pjTaskDao.save(task);
        pjTaskDao.updatefather(task);
        this.UpdateFatherCost(task);
    }

    @Override
    @Transactional
    public void update(PjTaskEntity task) {
        pjTaskDao.update(task);
        PjTaskEntity task1 = pjTaskDao.queryObject1(task);
        UpdateFatherPs(task1);
    }

    @Override
    @Transactional
    public void updateExProgress(PjTaskEntity task) {
        pjTaskDao.updateExProgress(task);
        PjTaskEntity task1 = pjTaskDao.queryObject1(task);
        UpdateFatherCost(task1);
    }

    @Override
    public void updateById(PjTaskEntity task) {
        pjTaskDao.updateById(task);
    }

    @Override
    public void deleteBatch(Long[] taskIds) {
        pjTaskDao.deleteBatch(taskIds);
    }

    @Override
    public List<PjTaskEntity> queryListByProj(String code) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        return pjTaskDao.queryList(map);
    }

    @Override
    public List<GanttLinkEntity> getLinkList(String code) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        return ganttLinkDao.queryList(map);
    }

    @Override
    public List<PjTaskEntity> queryChildTasks(String code, int fatherId) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("fatherId", fatherId);
        return pjTaskDao.queryList(map);
    }

    @Override
    @Transactional
    public void updateProgress(PjTaskEntity task, PjTaskDetEntity det) {
        if (null != det) {
            det.setUploadDate(new Date());
            pjTaskDelDao.save(det);
        }
        pjTaskDao.updateProgress(task);
        //
        PjTaskEntity task1 = pjTaskDao.queryObject(task.getId());
        UpdateFatherPs(task1);
    }

    @Override
    public List<GanttLinkEntity> queryLinks(Map<String, Object> map) {
        return ganttLinkDao.queryList(map);
    }

    @Override
    public List<PjTaskEntity> queryListWithLinkByProj(int projId) {
        Map<String, Object> map = new HashMap<>();
        map.put("projId", projId);
        return pjTaskDao.queryListWithLink(map);
    }

    @Override
    public Map<Integer, PjTaskEntity> queryMapWithLinkByProj(int projId) {
        Map<Integer, PjTaskEntity> map = new HashMap<>();
        List<PjTaskEntity> tasks = queryListWithLinkByProj(projId);
        if (tasks != null) {
            tasks.forEach((t) -> {
                map.put(t.getTaskid(), t);
            });
        }
        return map;
    }

    @Override
    public void saveLink(GanttLinkEntity ganttLink) {
        ganttLinkDao.save(ganttLink);
    }

    @Override
    @Transactional
    public void updateLink(GanttLinkEntity ganttLink) {
        ganttLinkDao.update(ganttLink);
        //计算延迟 2017-09-15
        PjTaskEntity source = new PjTaskEntity();
        source.setPjid(ganttLink.getPjid());
        source.setTaskid(ganttLink.getSource());
        source = pjTaskDao.queryObject1(source);
        updateNextTask(ganttLink.getPjid(), source);
    }

    //迭代更新后任务起止日期
    @Override
    @Transactional
    public void updateNextTask(int pid, PjTaskEntity source) {
        if (source == null) {
            return;
        }
        Map<String, Object> map = new HashMap();
        map.put("projId", pid);
        map.put("source", source.getTaskid());
        List<GanttLinkEntity> links = ganttLinkDao.queryList(map);
        if (links != null) {
            for (GanttLinkEntity l : links) {
                PjTaskEntity target = new PjTaskEntity();
                target.setPjid(pid);
                target.setTaskid(l.getTarget());
                target = pjTaskDao.queryObject1(target);
                if (target == null) {
                    return;
                }
                switch (l.getType()) {
                    case 0: //结束 开始
                        target.setT_start(DateUtils.addDays(source.getT_end(), l.getDelay()));
                        target.setT_end(DateUtils.addDays(target.getT_end(), l.getDelay()));
                        break;
                    case 1:
                        break;
                    case 2:
                        break;
                    case 3:
                        break;
                }
                pjTaskDao.update(target);
                updateNextTask(pid, target);
            }
        }
    }

    @Override
    public void delLink(GanttLinkEntity ganttLink) {
        ganttLinkDao.delete(ganttLink.getId());
    }

    /**
     * 紧后工作t_start,t_end, 本目标工作t_start1,t_end1, 关系类型 type 0：开始结束
     *
     * @param ganttLink
     * @return
     */
    @Override
    public int queryDelay(GanttLinkEntity ganttLink) {
        ParseUtils parser = new ParseUtils();
        Map map = ganttLinkDao.getTaskRef(ganttLink.getId());
        int type = parser.ToInt(map.get("type"));
        if (0 == type) {
            Long end1 = parser.ToDate(map.get("t_end1")).getTime();
            Long start = parser.ToDate(map.get("t_start")).getTime();
            int betweenDays = (int) ((end1 - start) / (1000 * 60 * 60 * 24) + 0.5);
            return betweenDays;
        }
        return 0;
    }

    @Override
    public List<PjTaskEntity> queryContractList(String code) {
        Map<String, Object> map = new HashMap();
        map.put("code", code);
        map.put("iscontract", 1);
        return pjTaskDao.queryContractList(map);
    }

    @Override
    public Map<String, Object> queryDateRange(String code) {
        Map<String, Object> map = new HashMap();
        map.put("code", code);
        return pjTaskDao.queryDateRange(map);
    }

    @Override
    public Map queryCostByMonth(String value) {
        return pjTaskDao.queryCostByMonth(value);
    }

    @Override
    public List<GanttLinkEntity> getPreTasks(Map<String, Object> map) {
        return ganttLinkDao.getPreTasks(map);
    }

    @Override
    public List<PjTaskEntity> queryFatherTask(String code) {
        return pjTaskDao.queryFatherTask(code);
    }

    @Override
    public List<KeyValueEntity> queryCzByYear(String code) {
        return pjTaskDao.queryCzByYear(code);
    }

    @Override
    public Map queryCzByQuarter(String code) {
        List<KeyValueEntity> monthSet = pjTaskDao.queryCzByMonth(code);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//小写的mm表示的是分钟
        Date staDate = null;
        Date endDate = null;
        try {
            staDate = sdf.parse(monthSet.get(0).getK());
            endDate = sdf.parse(monthSet.get(monthSet.size() - 1).getK());
        } catch (ParseException e) {
            LOGGER.error(e.getMessage(), e);
        }
        int monthStart = (int) (staDate.getYear() * 12 + staDate.getMonth() - 1);
        int monthEnd = (int) (endDate.getYear() * 12 + endDate.getMonth());
        StrBuilder str = new StrBuilder();
        str.append("select ");
        int i = 1;
        while (monthStart < monthEnd) {
            int y = monthStart / 12;
            int m = monthStart % 12 + 1;
            String strDate = sdf.format(new Date(y, m, 1));
            monthStart += 3;
            int y1 = monthStart / 12;
            int m1 = monthStart % 12;
            String enDate = sdf.format(new Date(y1, m1, 1));
            str.append(" SUM(CASE to_char(t_start,'yyyy-MM')>=to_char(to_date('"
                    + strDate + "', 'yyyy-MM'), 'yyyy-MM') and TO_CHAR(t_start,'yyyy-MM')<=to_char(to_date('"
                    + enDate + "','yyyy-MM'),'yyyy-MM')"
                    + " WHEN true "
                    + "THEN cost else 0 end) \"" + i + "\",");
            i++;

        }
        str.delete(str.length() - 1, str.length());
        str.append(" FROM pj_task where code=" + code + " and iscontract=1;");
        return queryCostByMonth(str.toString());
    }

    @Override
    public List<KeyValueEntity> queryCzByMonth(String code) {
        return pjTaskDao.queryCzByMonth(code);
    }

    @Override
    @Transactional
    public void updateLinks(PjTaskEntity task, List<GanttLinkEntity> linkEntityList) {
        Map<String, Object> map = new HashMap<>();
        map.put("target", task.getTaskid());
        map.put("pjid", task.getPjid());
        ganttLinkDao.deleteLink(map);
        if (task.getType() == 0) {
            ganttLinkDao.deleteLinkbySource(map);
        }
        if (linkEntityList.size() > 0) {
            ganttLinkDao.insertLinks(task.getPjid(), linkEntityList);
        }
    }

    /*
    更新父级进度
     */
    private PjTaskEntity UpdateFatherPs(PjTaskEntity task) {
        try {
            if (task != null && task.getFatherid() > 0) {
                PjTaskEntity f = pjTaskDao.queryObjectFather(task);
                Map<String, Object> map = new HashMap();
                map.put("pjid", f.getPjid());
                map.put("fatherid", f.getTaskid());
                pjTaskDao.updateParentProgress(map);
                //迭代父级
                UpdateFatherPs(f);
            }
        } catch (Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return null;
        }
        return null;
    }

    @Override
    public void UpdateFatherCost(PjTaskEntity task) {
        if (task != null && task.getFatherid() > 0) {
            ParseUtils parser = new ParseUtils();
            PjTaskEntity f = pjTaskDao.queryObjectFather(task);
            Map<String, Object> map = new HashMap();
            map.put("code", f.getCode());
            map.put("fatherid", f.getTaskid());
            pjTaskDao.updateParentCost(map);
            Map dateRangeMap = pjTaskDao.queryDateRange(map);
            PjTaskEntity obj = new PjTaskEntity();
            obj.setId(f.getId());
            obj.setT_start(parser.ToDate(dateRangeMap.get("min")));
            obj.setT_end(parser.ToDate(dateRangeMap.get("max")));
            obj.setType(f.getType());
            //更新时间范围、总成本
            pjTaskDao.updateExCostAndProgessById(obj);
            UpdateFatherCost(f);
        }
    }

    @Override
    public List<PjTaskEntity> queryChildbyPid(String code) {
        return pjTaskDao.queryChildbyPid(code);
    }

    @Override
    public List<PjTaskEntity> queryAllTask() {
        return pjTaskDao.queryAllTask();
    }

    @Override
    public PjTaskEntity queryObjectByChildName(String code, Integer type) {
        String child_name = ChildProEnum.getName(type);
        Map map = new HashMap();
        map.put("title", child_name);
        map.put("code", code);
        return pjTaskDao.queryObjectByChildName(map);
    }

    @Override
    public void updateTaskProgress(String code, Integer type, BigDecimal progress) {
        PjTaskEntity task = this.queryObjectByChildName(code, type);
        if (task != null) {
            task.setProgress(progress.doubleValue());
        }
        this.update(task);
    }

    @Override
    public List<PjTaskEntity> queryChildList(Integer id) {
        return pjTaskDao.queryChildList(id);
    }

    @Override
    public void delete(Integer id) {
        pjTaskDao.delete(id);
    }

}
